#ifndef HANDDETECTOR_H
#define HANDDETECTOR_H

#include <vector>
#include <cv.h>

#include "handgestureexception.h"

namespace mlgesture {

class HandDetector {

public:
	HandDetector(const cv::Mat &img, int min_area = 600);
	~HandDetector();
	std::vector<cv::Rect> getHands() const;
	void process(const cv::Mat &img) throw (HandGestureException);
	void clear();

private:
	class ContourInfo {
	public:
		int id_;
		double area_;

		ContourInfo(int id) : id_(id) {}
		bool operator< (const ContourInfo &contour) const;
		bool operator> (const ContourInfo &contour) const;
	};

	cv::Mat imgSource_;
	cv::Mat imgTemp_;
	std::vector<std::vector<cv::Point> > contours_;
	std::vector<ContourInfo*> contoursInfo_;
	std::vector<cv::Rect> handsRect_;
	std::vector<cv::Rect> potentialHands_;
	int minContourArea_;

	struct cmpContourInfo {
		inline bool operator() (const ContourInfo *a, const ContourInfo *b) {
			return *a > *b;
		}
	};
	void findContours(std::vector<std::vector<cv::Point> > &contours, int contours_to_find = -1);
	bool checkContour(std::vector<cv::Point> &contour_, cv::Rect &hand);
	void clearContours();
	void calculateParams(const std::vector<cv::Point> &contour, std::vector<double> &cosine, std::vector<int> &direction);
	void checkParams(const std::vector<double> &cosine, const std::vector<int> &direction,
					 std::vector<int> &contour_state, std::vector<int> &max_pos);
	bool analyzeSequence(const std::vector<int> contour_state, const std::vector<int> max_pos, int contour_size,
						 int &first_point, int &last_point, int &hand_points_number);

	static const float FINGER_THRESHOLD;
	static const float VALLEY_THRESHOLD;
	static const float FALSE_THRESHOLD;
};

}

#endif // HANDDETECTOR_H
